from __future__ import absolute_import

from elasticsearch import *
from elasticsearch import helpers
from dejavu.database import Database
    
class EsDatabase(Database):
    """
    Queries:

    1) Find duplicates (shouldn't be any, though):

        select `hash`, `song_id`, `offset`, count(*) cnt
        from fingerprints
        group by `hash`, `song_id`, `offset`
        having cnt > 1
        order by cnt asc;

    2) Get number of hashes by song:

        select song_id, song_name, count(song_id) as num
        from fingerprints
        natural join songs
        group by song_id
        order by count(song_id) desc;

    3) get hashes with highest number of collisions

        select
            hash,
            count(distinct song_id) as n
        from fingerprints
        group by `hash`
        order by n DESC;

    => 26 different songs with same fingerprint (392 times):

        select songs.song_name, fingerprints.offset
        from fingerprints natural join songs
        where fingerprints.hash = "08d3c833b71c60a7b620322ac0c0aba7bf5a3e73";
    """

    type = "es"

    def __init__(self, **options):
        super(EsDatabase, self).__init__()
        print('init es dal')
        host = 'localhost'
        self.es = Elasticsearch(
            hosts=[{'host': host, 'port': 9200}],
            use_ssl=False,
            verify_certs=False,
            connection_class=RequestsHttpConnection
            )
        self.songid = 0
        self.count = 0
        self.index_name = 'http-demo'
        self.type_str = 'http'
        self._options = options

    def after_fork(self):
        # Clear the cursor cache, we don't want any stale connections from
        # the previous process.
        ''''''

    def setup(self):
        """
        Creates any non-existing tables required for dejavu to function.

        This also removes all songs that have been added but have no
        fingerprints associated with them.
        """

    def empty(self):
        """
        Drops tables created by dejavu and then creates them again
        by calling `SQLDatabase.setup`.

        .. warning:
            This will result in a loss of data
        """

    def delete_unfingerprinted_songs(self):
        """
        Removes all songs that have no fingerprints associated with them.
        """

    def get_num_songs(self):
        """
        Returns number of songs the database has fingerprinted.
        """

    def get_num_fingerprints(self):
        """
        Returns number of fingerprints the database has fingerprinted.
        """

    def set_song_fingerprinted(self, sid):
        """
        Set the fingerprinted flag to TRUE (1) once a song has been completely
        fingerprinted in the database.
        """

    def get_songs(self):
        """
        Return songs that have the fingerprinted flag set TRUE (1).
        """
        return list()

    def get_song_by_id(self, sid):
        """
        Returns song by its ID.
        """

    def insert(self, hash, sid, offset):
        """
        Insert a (sha1, song_id, offset) row into database.
        """

    def insert_song(self, songname, file_hash):
        """
        Inserts song in the database and returns the ID of the inserted record.
        """
        self.songid += 1
        return self.songid

    def query(self, hash):
        """
        Return all tuples associated with hash.

        If hash is None, returns all entries in the
        database (be careful with that one!).
        """
        # select all if no key

    def get_iterable_kv_pairs(self):
        """
        Returns all tuples in database.
        """
        return self.query(None)

    def insert_hashes(self, sid, hashes, songname = '', file_hash = ''):
        """
        Insert series of hash => song_id, offset
        values into the database.
        """
        actions = list()
        for _hash in hashes:
            data = {
                'songid' : self.songid,
                'songname' : songname,
                'file_hash' : file_hash,
                'fp_id': self.count,
                'fingerprinted': 1,
                'hash': _hash[0],
                'offset': _hash[1]
            }
            action = {
               "_index": self.index_name,
               "_type": self.type_str,
               "_id": self.count,
               "_source": data
            }
            actions.append(action)
            self.count += 1
            
        helpers.bulk(self.es, actions)

    def return_matches(self, hashes):
        """
        Return the (song_id, offset_diff) tuples associated with
        a list of (sha1, sample_offset) values.
        """
        